package com.es.springbootes.controller.api;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.es.springbootes.entity.LivingData;
import com.es.springbootes.scoll.service.JsoupDataService;
import com.es.springbootes.util.R;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.jetbrains.annotations.NotNull;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.client.RestTemplate;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * @author 邹宇杰
 * @email 2901570623@qq.com
 * @site http://zouyujie.top
 * @date 2022/2/13 12:59
 */
@RestController
public class BigDataController {

    private static final Logger logger = LoggerFactory.getLogger(BigDataController.class);

    @Autowired
    @Qualifier("restHighLevelClient")
    private RestHighLevelClient client;

    @GetMapping("/getDataList/{from}")
    public R get(@PathVariable("from") int from){
        SearchRequest request = new SearchRequest("livingdata");
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.from(from);
        sourceBuilder.size(50);
        sourceBuilder.sort("totalCount", SortOrder.DESC);
        sourceBuilder.query(QueryBuilders.boolQuery().mustNot(QueryBuilders.matchQuery("liveSourceType", 0)));
        request.source(sourceBuilder);
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<Map<String, Object>> result = new ArrayList<>();
        assert response != null;
        for (SearchHit hit : response.getHits().getHits()) {
            result.add(hit.getSourceAsMap());
        }
        return R.ok().put("data", result);
    }

    @GetMapping("/searchDataList")
    public R get(@RequestParam @NotNull String keyword){
        SearchRequest request = new SearchRequest("livingdata");
        SearchSourceBuilder builder = new SearchSourceBuilder();
            builder.query(
                    QueryBuilders.boolQuery()
                            .should(QueryBuilders.matchQuery("nick", keyword))
                            .should(QueryBuilders.matchQuery("gameFullName", keyword))
                            .should(QueryBuilders.matchQuery("introduction", keyword))
                            .should(QueryBuilders.matchQuery("roomName", keyword))
            );
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        builder.highlighter(highlightBuilder.field("nick").field("gameFullName").field("introduction").field("roomName"));
        builder.sort("totalCount", SortOrder.DESC);
        builder.from(0);
        builder.size(50);
        request.source(builder);
        SearchResponse response = null;
        try {
            response = client.search(request, RequestOptions.DEFAULT);
        } catch (IOException e) {
            e.printStackTrace();
        }
        List<Map<String, Object>> result = new ArrayList<>();
        assert response != null;

        SearchHit[] hits = response.getHits().getHits();
        for (SearchHit hit : hits) {
            Map<String, HighlightField> fieldMap = hit.getHighlightFields();

            HighlightField nickfields = fieldMap.get("nick");
            String nick = "";
            if(nickfields != null){
                Text[] nicksfragments = nickfields.fragments();
                for (Text text : nicksfragments) {
                    nick += text;
                }
            }

            HighlightField gameFullNameFields = fieldMap.get("gameFullName");
            String gameFullName = "";
            if(gameFullNameFields != null){
                Text[] gameFullNameFragments = gameFullNameFields.fragments();
                for (Text text : gameFullNameFragments) {
                    gameFullName += text;
                }
            }

            HighlightField introductionFields = fieldMap.get("introduction");
            String introduction = "";
            if(introductionFields != null){
                Text[] introductionFragments = introductionFields.fragments();
                for (Text text : introductionFragments) {
                    introduction += text;
                }
            }

            HighlightField roomNameFields = fieldMap.get("roomName");
            String roomName = "";
            if(roomNameFields != null){
                Text[] roomNameFragments = roomNameFields.fragments();
                for (Text text : roomNameFragments) {
                    roomName += text;
                }
            }


            Map<String, Object> sourceAsMap = hit.getSourceAsMap();
            if(!"".equals(nick)){
                sourceAsMap.put("nick", nick);
            }
            if(!"".equals(gameFullName)){
                sourceAsMap.put("gameFullName", gameFullName);
            }
            if(!"".equals(introduction)){
                sourceAsMap.put("introduction", introduction);
            }
            if(!"".equals(roomName)){
                sourceAsMap.put("roomName", roomName);
            }

            result.add(sourceAsMap);
        }
        return R.ok().put("data", result);
    }

    @PostMapping("refreshDataList")
    public void refreshDataList(){
        try{
            RestTemplate restTemplate = new RestTemplate();
            int PageCount = 144;
            //每次更新144页
            for(int i = 0; i < PageCount; i++){
                String livingjsondata = restTemplate.getForObject(
                        "https://www.huya.com/cache.php?m=LiveList&do=getLiveListByPage&tagAll=0&callback=getLiveListJsonpCallback&page="+i,
                        String.class);
                String jsondata = livingjsondata.replaceAll("getLiveListJsonpCallback", "").replaceAll("[\\(\\)]", "");
                JSONObject jsonObject = JSONObject.parseObject(jsondata);
                JSONObject data = jsonObject.getJSONObject("data");
                JSONArray datas = data.getJSONArray("datas");
                List<LivingData> dataList = JSONArray.parseArray(datas.toJSONString(), LivingData.class);
                //直播平台的数据进入mysql备份

                //将直播平台的数据全部注入Es中分析
                BulkRequest bulkRequest = new BulkRequest();
                bulkRequest.timeout(TimeValue.timeValueMinutes(2));
                bulkRequest.timeout("2m");
                for (LivingData livingData : dataList) {
                    bulkRequest.add(
                            new IndexRequest("livingdata")
                                    .id(String.valueOf(livingData.getProfileRoom()))
                                    .source(JSONObject.toJSONString(livingData), XContentType.JSON));
                }
                BulkResponse bulk = client.bulk(bulkRequest, RequestOptions.DEFAULT);
                if(bulk.hasFailures()){
                    logger.error(bulk.buildFailureMessage());
                }
                logger.info("第"+i+"页的当前批量任务状态:"+bulk.status().toString());
            }
        }catch(Exception e){
            e.printStackTrace();
        }
    }
}